package gui;

/**
 * This class implements a table that displays and allows the user to edit the
 * users for a role.
 *
 * @author Aaron A. Lovato
 */
 
import backend.*;
import javax.swing.table.*;
import java.util.*;
import javax.swing.event.*;
import javax.swing.JOptionPane;
import javax.swing.*;

public class UserTableModel extends AbstractTableModel 
                                implements TableModelListener
{
    private String[] columns;
    private Object[][] data;
    private Role role;
    private boolean editable;
    
    public UserTableModel(Role role, boolean editable)
    {
        // Save the associated role
        this.role = role;
        this.editable = editable;
        
        //Add the default values to the equation table
        columns = new String[2];
        columns[0] = "Username";
        columns[1] = "Password";
        data = new Object[0][2];
        
        int row = 0;
        if (this.role != null)
        {
            HashMap<String, User> users = this.role.getUsers();
            for(String s : users.keySet())
            {
                Object[] newRow = new Object[2];
                newRow[0] = s;
                newRow[1] = users.get(s).getPassword();
                addRow(newRow);
            }
        }
        Object[] newRow = new Object[2];
        newRow[0] = "";
        newRow[1] = "";
        addRow(newRow);
            
        
        addTableModelListener(this);
    }
    
    public void setEditable(boolean editable)
    {
        this.editable = editable;
    }
    
    public int getColumnCount()
    {
        return columns.length;
    }
    
    public int getRowCount()
    {
        return data.length;
    }
    
    public String getColumnName(int col) 
    {
        return columns[col];
    }

    public Object getValueAt(int row, int col) 
    {
        return data[row][col];
    }
    
    public Class getColumnClass(int c) 
    {
        return getValueAt(0, c).getClass();
    }

    public boolean isCellEditable(int row, int col) 
    {
        if (!editable)
            return false;
        if(row == data.length - 1 || col == 1)
            return true;
        else
            return false;
    }

    public void setValueAt(Object value, int row, int col) 
    {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }
    
    public void addRow(Object[] row)
    {
        int newLength = data.length + 1;
        Object[][] newData = new Object[newLength][2];
        System.arraycopy(data, 0, newData, 0, data.length);
        data = newData;
        data[newLength-1][0] = row[0];
        data[newLength-1][1] = row[1];
        fireTableRowsInserted(data.length, data.length);
    }
    
    public void tableChanged(TableModelEvent e)
    {
        //Extend the table when a new row is filled
        if(e.getType() == TableModelEvent.UPDATE && e.getFirstRow() == (data.length - 1))
        {         
            String name = (String) data[data.length-1][0];
            String password = (String) data[data.length-1][1];
            if(name == null || name.compareTo("") == 0)
                return;
            
            // Make sure this user isn't duplicated
            for (int i = 0; i < data.length; i++)
            {
                if (name.compareTo((String)data[i][0]) == 0)
                {
                    if(i != data.length-1)
                    {
                        JOptionPane.showMessageDialog(null, "This user is already assigned to this role",
                                                      "Error", JOptionPane.ERROR_MESSAGE);
                        data[data.length-1][0] = "";
                        return;
                    }
                }
            }
            
            // Check if this user is known to the server
            if (role.getServer().getUsers().containsKey(name))
            {
                // Assign the user
                try {
                    role.getServer().assignUser(name, role.getName());
                }
                catch (Exception error)
                {
                    JOptionPane.showMessageDialog(null, "Oh god how did this get here, I am not good with computer",
                    "Error", JOptionPane.ERROR_MESSAGE, new ImageIcon("resources/cat.jpg"));
                }
                
                // Update the user's password
                int load = JOptionPane.showConfirmDialog(null,
                                                      "This user already exists. Do you want to load his/her password?",
                                                      "User already exists!",
                                                      JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE);
                if (load == 0)
                {
                    password = role.getServer().getUsers().get(name).getPassword();
                    data[data.length-1][1] = password;
                }        
                addRow(new Object[2]);
                
                                                                    
            }
            else
            {
                try
                {
                    // Don't add a permission if the value isn't set
                    if (password.compareTo("") != 0)
                    {
                        role.getServer().addUser(name, password);
                        role.getServer().assignUser(name, role.getName());
                        addRow(new Object[2]);
                    }
                    
                }
                catch(Exception error)
                {
                    JOptionPane.showMessageDialog(null, error.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                    data[data.length-1][0] = "";
                    data[data.length-1][1] = "";                
                }            
            }
        }
        else if(e.getColumn() == 1)
        {
            // Update the changed permission
            String name = (String) data[e.getFirstRow()][0];
            String value = (String) data[e.getFirstRow()][1];
            if(name == null || name == "")
                return;
            try
            {
                role.getServer().setPassword(name, value);
            }
            catch(Exception error)
            {
                    JOptionPane.showMessageDialog(null, error.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
        
    }
    
    public void setRole(Role role)
    {
        this.role = role;
        data = new Object[0][2];
        
        int row = 0;
        if (this.role != null)
        {
            HashMap<String, User> users = this.role.getUsers();
            for(String s : users.keySet())
            {
                Object[] newRow = new Object[2];
                newRow[0] = s;
                newRow[1] = users.get(s).getPassword();
                addRow(newRow);
            }
        }

        Object[] newRow = new Object[2];
        newRow[0] = "";
        newRow[1] = "";
        addRow(newRow);

        
        fireTableDataChanged();
    }
    
    public void deleteRow(int oldRow)
    {
        // Get the name of the permission to delete
        String name = (String) data[oldRow][0];
        try
        {
            role.getServer().unassignUser(role.getName(), name);
//             role.removeUser(role.getUsers().get(name));
        }
        catch (Exception error)
        {
            JOptionPane.showMessageDialog(null, "Oh god how did this get here, I am not good with computer",
                                          "Error", JOptionPane.ERROR_MESSAGE, new ImageIcon("resources/cat.jpg"));
        }
        
        // Rebuild data
        data = new Object[0][2];
        
        int row = 0;
        if (this.role != null)
        {
            HashMap<String, User> users = this.role.getUsers();
            for(String s : users.keySet())
            {
                Object[] newRow = new Object[2];
                newRow[0] = s;
                newRow[1] = users.get(s).getPassword();
                addRow(newRow);
            }
        }
        
        Object[] newRow = new Object[2];
        newRow[0] = "";
        newRow[1] = "";
        addRow(newRow);
        
        fireTableDataChanged();
    }
    
    public void rebuildTable()
    {
        // God knows what happened so rebuild this faggotry
        data = new Object[0][2];
        
        int row = 0;
        if (this.role != null)
        {
            HashMap<String, User> users = this.role.getUsers();
            for(String s : users.keySet())
            {
                Object[] newRow = new Object[2];
                newRow[0] = s;
                newRow[1] = users.get(s).getPassword();
                addRow(newRow);
            }
        }
        Object[] newRow = new Object[2];
        newRow[0] = "";
        newRow[1] = "";
        addRow(newRow);
    }
}

